﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using TravelServer.Services;
using AutoMapper;
using TravelServer.Models;
using TravelServer.Dtos;
using System.Text.RegularExpressions;
using TravelServer.ResourceParameters;
using TravelServer.DTOs;
using Microsoft.AspNetCore.Authorization;
using TravelServer.Helper;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Newtonsoft.Json;
using System.Reflection.Metadata;

namespace TravelServer.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TouristRoutsController : ControllerBase
    {
        private readonly ITouristRoutsRepository touristRoutsRepository;
        private readonly IMapper mapper;
        private readonly IUrlHelper urlHelper;
        private readonly IPropertyMappingService _propertyMappingService;

        public TouristRoutsController(ITouristRoutsRepository touristRoutsRepository
            , IMapper imap,
             IUrlHelperFactory urlHelperFactory,
            IActionContextAccessor actionContextAccessor,
            IPropertyMappingService propertyMappingService

            )
        {
            this.touristRoutsRepository = touristRoutsRepository;
            this.mapper = imap;
            this.urlHelper = urlHelperFactory.GetUrlHelper(actionContextAccessor.ActionContext);
            
        }

        private string GenerateTouristRouteResourceURL(
          TouristRouteResourceParamaters paramaters,
          PaginationResourceParamaters paramaters2,
          ResourceUriType type
      )
        {
            return type switch
            {
                ResourceUriType.PreviousPage => urlHelper.Link("GetTouristRoutes",
                    new
                    {
                        fileds= paramaters.ShapFileds,
                        keyword = paramaters.Keyword,
                        rating = paramaters.Rating,
                        pageNumber = paramaters2.PageNumber - 1,
                        pageSize = paramaters2.PageSize
                    }),
                ResourceUriType.NextPage => urlHelper.Link("GetTouristRoutes",
                    new
                    {
                        fileds = paramaters.ShapFileds,
                        keyword = paramaters.Keyword,
                        rating = paramaters.Rating,
                        pageNumber = paramaters2.PageNumber + 1,
                        pageSize = paramaters2.PageSize
                    }),
                _ => urlHelper.Link("GetTouristRoutes",
                    new
                    {
                        fileds = paramaters.ShapFileds,
                        keyword = paramaters.Keyword,
                        rating = paramaters.Rating,
                        pageNumber = paramaters2.PageNumber,
                        pageSize = paramaters2.PageSize
                    })
            };
        }


        //FromQuery 标记参数是查询参数，地址格式如下
        //baseRUL+/api/TouristRouts?keyworld=keyworld  ob
        //http://localhost:5126/api/TouristRouts?Keyword=%E6%B3%95%E5%9B%BD&RatingOperator=largerThan&RatingValue=2&Rating=2
        [HttpGet(Name = "GetTouristRoutes")]//标记该接口的URL名称，可获取
        public async Task<IActionResult> GetTouristRoutes(
            [FromQuery] TouristRouteResourceParamaters paramater1,
            [FromQuery] PaginationResourceParamaters paramater2
            )
        {

            if (!_propertyMappingService
               .IsMappingExists<TouristRouteDto, TouristRoute>(
               paramater1.OrderBy))
            {
                return BadRequest("请输入正确的排序参数");
            }

            if (!_propertyMappingService
               .IsMappingExists<TouristRouteDto,TouristRoute>(paramater1.ShapFileds))
            {
                return BadRequest("请输入正确的塑性参数");
            }

            var touristRoutePageList = await touristRoutsRepository.GetTouristRouteListAsync(paramater1.Keyword, paramater1.RatingOperator, paramater1.RatingValue, paramater2.PageNumber, paramater2.PageSize,paramater1.OrderBy);
            if (touristRoutePageList == null || touristRoutePageList.Count() == 0)
            {
                return NotFound("没有查询到相关路线!");
            }
            var dtos = mapper.Map<IEnumerable<TouristRouteDto>>(touristRoutePageList);
            var previousPageLink= touristRoutePageList.HasPrevious?GenerateTouristRouteResourceURL(paramater1,paramater2,ResourceUriType.PreviousPage):null;
            var nextPageLink= touristRoutePageList.HasNext?GenerateTouristRouteResourceURL(paramater1, paramater2, ResourceUriType.NextPage) : null;

            //创建Header参数X-pagination 匿名函数

            var headerLink = new
            {
                previousPageLink,
                nextPageLink,
                totalCount=touristRoutePageList.TotalCount,
                pageSize=touristRoutePageList.PageSize,
                currentPage=touristRoutePageList.PageNumber,
                totalPages=touristRoutePageList.TotalPages
            };

          

            //给响应头部添加键值对
            Response.Headers.Add("X-pagination", JsonConvert.SerializeObject(headerLink));
            
            return Ok(dtos.ShapeData<TouristRouteDto>(paramater1.ShapFileds));
        }

        //[FromRoute] 标记参数为路由参数,需要与[HttpGet("{touristRouteId}")]名称一致。
        //也可以不标记，默认为路由参数
        //baseRUL+/api/TouristRouts/touristRouteId
        //Name是给这个URL定义的名称，可以通过名称拿到URL
        [HttpGet("{touristRouteId}", Name = "GetTouristRouteById")]
        public async Task<IActionResult> GetTouristRouteById([FromRoute] Guid touristRouteId)
        {
            var touristRoute = await touristRoutsRepository.GetTouristRouteAsync(touristRouteId);
            if (touristRoute == null)
            {
                return NotFound();
            }
            var dto = mapper.Map<Dtos.TouristRouteDto>(touristRoute);
            return Ok(dto);

        }

        [Authorize(AuthenticationSchemes = "Bearer")]
        //[Authorize(Roles ="Admin")]
        [HttpPost("Create")]
        //由于GUID是后端创建的，前端传给后端时，专门采用没有GUID的传输模型
        public async Task<IActionResult> CreateRouristRoute([FromBody] TouristRouteCreationDto touristRouteCreationDto)
        {
            var touristRouteFromDto = mapper.Map<TouristRoute>(touristRouteCreationDto);
            touristRoutsRepository.ADDTouristRoute(touristRouteFromDto);
            //post请求需要返回
            var res = await touristRoutsRepository.SaveDataAsync();
            if (res)
            {
                var touristRoutDto = mapper.Map<TouristRouteDto>(touristRouteFromDto);
                //post成功 返回201 CreatedAtRoute  类似return ok的用法
                var postResult = CreatedAtRoute(
                    "GetTouristRouteById", //返回URL，通过id可以查询到保存的结果,该地址保存在Header里的Location
                    new { touristRouteId = touristRoutDto.Id },////URL参数对象
                    touristRoutDto);//返回的值

                return postResult;
            }
            return BadRequest();
        }

        [HttpPut("{touristRouteId}")]
        public async Task<IActionResult> UpdateTouristRoute([FromRoute] Guid touristRouteId, [FromBody] TouristRouteUpdateDto touristRouteUpdateDto)
        {
            var touristRouteFromRepo = await touristRoutsRepository.GetTouristRouteAsync(touristRouteId);
            if (touristRouteFromRepo == null)
            {
                return NotFound();
            }

            mapper.Map(touristRouteUpdateDto, touristRouteFromRepo);

            bool res = await touristRoutsRepository.SaveDataAsync();
            if (res)
            {
                return NoContent();
            }
            return BadRequest();
        }

        [HttpDelete("{touristRouteId}")]
        public async Task<IActionResult> DeleteTouristRoute([FromRoute] Guid touristRouteId)
        {

            var touristRouteFromRepo = await touristRoutsRepository.GetTouristRouteAsync(touristRouteId);
            if (touristRouteFromRepo == null)
            {
                return NotFound();
            }
            touristRoutsRepository.DeleteTouristRoute(touristRouteFromRepo);

            bool res = await touristRoutsRepository.SaveDataAsync();
            if (res)
            {
                return NoContent();
            }
            return BadRequest();

        }

        [HttpDelete]
        public async Task<IActionResult> DeleteTouristRoutes([FromQuery] IEnumerable<Guid> ids)
        {

            var touristRoutes = await touristRoutsRepository.GetTourisRoutesAsync(ids);
            if (touristRoutes == null || touristRoutes.Any(t => t == null) || touristRoutes.Count() == 0)
            {
                return NotFound();
            }
            touristRoutsRepository.DeleteTourisRoutes(touristRoutes);
            await touristRoutsRepository.SaveDataAsync();
            return NoContent();
        }
    }
}
